/*
 * BigInteger.h
 *
 *  Created on: 07.04.2014
 *      Author: Nicolas Winkler
 */

#ifndef _MATH_BIGINTEGER_H
#define _MATH_BIGINTEGER_H

#include "Integers.h"
#include <string>
#include <vector>


namespace math
{
	class BigInteger;
}


class math::BigInteger
{
	Int64 value;
public:
	BigInteger(void);
	BigInteger(const BigInteger& value);
	BigInteger(long long value);
	~BigInteger(void);

	const BigInteger& 		operator =	(const BigInteger& value);
	const BigInteger& 		operator +=	(const BigInteger& summand);
	const BigInteger& 		operator -=	(const BigInteger& subtrahend);
	const BigInteger& 		operator *=	(const BigInteger& factor);
	const BigInteger& 		operator /=	(const BigInteger& divisor);
	const BigInteger& 		operator %=	(const BigInteger& divisor);

	const BigInteger 		operator + 	(const BigInteger& summand) const;
	const BigInteger 		operator - 	(const BigInteger& subtrahend) const;
	const BigInteger 		operator * 	(const BigInteger& factor) const;
	const BigInteger 		operator / 	(const BigInteger& divisor) const;
	const BigInteger 		operator %	(const BigInteger& divisor) const;

	bool			 		operator <	(const BigInteger& b) const;
	bool			 		operator >	(const BigInteger& b) const;
	bool			 		operator <=	(const BigInteger& b) const;
	bool			 		operator >=	(const BigInteger& b) const;
	bool			 		operator ==	(const BigInteger& b) const;
	bool			 		operator !=	(const BigInteger& b) const;

	std::string 			getAsString	(void) const;

	/**
	 * calculates power expressions
	 * \return base to the power of exponent
	 */
	static const BigInteger	pow			(const BigInteger& base, const BigInteger& exponent);

	/**
	 * calculates a specific root of an integer.
	 *
	 * \param base the number to find the root
	 * \param invExp which root
	 * \return base ^ (1 / invExp)
	 */
	static const BigInteger	root		(const BigInteger& base, const BigInteger& invExp);

	static const BigInteger	ggt			(const BigInteger& a, const BigInteger& b);
	static void				cancel		(BigInteger& numerator, BigInteger& denominator);

	struct PrimeFactor
	{
		int factor;
		int amount;
		PrimeFactor(int factor, int amount);
	};

	static std::vector<PrimeFactor> getPrimeFactors(const BigInteger& number);
};



#endif // _MATH_BIGINTEGER_H
